using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;

namespace cb0tServer
{
    class WebClientObject
    {
        private List<byte> receive_dump = new List<byte>();
        private Queue<byte[]> outbound_queue = new Queue<byte[]>();

        public Socket socket = null;

        public String RequestedUrl = String.Empty;
        public String ProtocolVersion = String.Empty;
        public String UserAgent = String.Empty;
        public String ContentType = String.Empty;
        public String[] AcceptedContentType = new String[] { };

        public IPAddress ip;
        public ushort port;
        public int spawn_time;
        public int receive_fails;
        public bool request_obtained;
        public long file_length;

        public WebClientObject() { }

        public WebClientObject(Socket socket)
        {
            this.request_obtained = false;
            this.spawn_time = (int)cb0tServer.Helpers.UnixTime();
            this.receive_fails = 0;
            this.socket = socket;
            this.socket.Blocking = false;
            this.ip = ((IPEndPoint)this.socket.RemoteEndPoint).Address;
            this.port = (ushort)(((IPEndPoint)this.socket.RemoteEndPoint).Port);
        }

        public bool SendPacket()
        {
            if (this.outbound_queue.Count == 0) return false;

            byte[] buffer1 = this.outbound_queue.Peek();
            int bytes_sent = 0;
            SocketError e = SocketError.Success;

            try
            {
                bytes_sent = this.socket.Send(buffer1, 0, buffer1.Length, SocketFlags.None, out e);
            }
            catch { }

            if (bytes_sent == 0) // still connected?
            {
                if (e == SocketError.WouldBlock)
                {
                    this.receive_fails = 0;
                }
                else
                {
                    if (this.receive_fails++ > 3)
                    {
                        this.Disconnect();
                        return true;
                    }
                }
            }
            else // packet sent
            {
                this.receive_fails = 0;
                this.outbound_queue.Dequeue();
            }

            return true;
        }
        public void test() { Console.WriteLine(outbound_queue.Count.ToString()); }
        public void AddPacket(byte[] packet)
        {
            this.outbound_queue.Enqueue(packet);
        }

        public void AddBytes(byte[] received)
        {
            this.receive_dump.AddRange(received);
        }

        public byte[] GetBytes()
        {
            return this.receive_dump.Count > 0 ? this.receive_dump.ToArray() : null;
        }

        public void RemoveBytes(int count)
        {
            this.receive_dump.RemoveRange(0, count);
        }

        public bool IsSet()
        {
            return this.socket != null;
        }

        public void Disconnect()
        {
            this.receive_dump.Clear(); // more efficient GC
            this.outbound_queue.Clear(); // more efficient GC

            try
            {
                this.socket.Disconnect(false);
            }
            catch { }

            this.socket = null;
        }

    }
}
